using System;
using System.Reflection;

using TrueCode.Core.Aspects;


namespace TrueCode.DependencyManager.Services.InjectionPoints
{
  [Serializable]
  public class NamedMethod : IMethod, IComparable< NamedMethod >
  {
    #region Fields
    private readonly int _executionOrder;
    private readonly string _methodName;
    #endregion

    #region .ctors
    public NamedMethod( [NotNull] string methodName ) : this( methodName, 0 )
    {
    }

    public NamedMethod( [NotNull] string methodName, int executionOrder )
    {
      if( methodName == null ) throw new ArgumentNullException( "methodName" );
      _executionOrder = executionOrder;
      _methodName = methodName;
    }
    #endregion

    #region Protected
    protected int ExecutionOrder
    {
      get { return _executionOrder; }
    }

    protected string MethodName
    {
      get { return _methodName; }
    }
    #endregion

    #region Implementation of IMethod
    [NotNull]
    public virtual MethodInfo GetMethod( Type type )
    {
      var methodInfo = type.GetMethod( _methodName );

      #region Assert that methodInfo has been got
      if( methodInfo == null )
      {
        var exc = new InvalidOperationException( "Type does not have specified method" );
        exc.Data.Add( "Type", type );
        exc.Data.Add( "Method", _methodName );
        throw exc;
      }
      #endregion

      return methodInfo;
    }
    #endregion

    #region Implementation of IComparable<NamedMethod>
    public virtual int CompareTo( NamedMethod other )
    {
      return other == null ? 1 : _executionOrder.CompareTo( other._executionOrder );
    }
    #endregion

    #region Implementation of IComparable
    public virtual int CompareTo( object obj )
    {
      return CompareTo( obj as NamedMethod );
    }
    #endregion
  }
}